home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / pyshared / PIL / BmpImagePlugin.py < prev    next >
Text File  |  2006-12-03  |  7KB  |  246 lines

  1. #
  2. # The Python Imaging Library.
  3. # $Id: BmpImagePlugin.py 2134 2004-10-06 08:55:20Z fredrik $
  4. #
  5. # BMP file handler
  6. #
  7. # Windows (and OS/2) native bitmap storage format.
  8. #
  9. # history:
  10. # 1995-09-01 fl   Created
  11. # 1996-04-30 fl   Added save
  12. # 1997-08-27 fl   Fixed save of 1-bit images
  13. # 1998-03-06 fl   Load P images as L where possible
  14. # 1998-07-03 fl   Load P images as 1 where possible
  15. # 1998-12-29 fl   Handle small palettes
  16. # 2002-12-30 fl   Fixed load of 1-bit palette images
  17. # 2003-04-21 fl   Fixed load of 1-bit monochrome images
  18. # 2003-04-23 fl   Added limited support for BI_BITFIELDS compression
  19. #
  20. # Copyright (c) 1997-2003 by Secret Labs AB
  21. # Copyright (c) 1995-2003 by Fredrik Lundh
  22. #
  23. # See the README file for information on usage and redistribution.
  24. #
  25.  
  26.  
  27. __version__ = "0.7"
  28.  
  29.  
  30. import string
  31. import Image, ImageFile, ImagePalette
  32.  
  33.  
  34. #
  35. # --------------------------------------------------------------------
  36. # Read BMP file
  37.  
  38. def i16(c):
  39.     return ord(c[0]) + (ord(c[1])<<8)
  40.  
  41. def i32(c):
  42.     return ord(c[0]) + (ord(c[1])<<8) + (ord(c[2])<<16) + (ord(c[3])<<24)
  43.  
  44.  
  45. BIT2MODE = {
  46.     # bits => mode, rawmode
  47.     1: ("P", "P;1"),
  48.     4: ("P", "P;4"),
  49.     8: ("P", "P"),
  50.     16: ("RGB", "BGR;16"),
  51.     24: ("RGB", "BGR"),
  52.     32: ("RGB", "BGRX")
  53. }
  54.  
  55. def _accept(prefix):
  56.     return prefix[:2] == "BM"
  57.  
  58. ##
  59. # Image plugin for the Windows BMP format.
  60.  
  61. class BmpImageFile(ImageFile.ImageFile):
  62.  
  63.     format = "BMP"
  64.     format_description = "Windows Bitmap"
  65.  
  66.     def _bitmap(self, header = 0, offset = 0):
  67.  
  68.         if header:
  69.             self.fp.seek(header)
  70.  
  71.         read = self.fp.read
  72.  
  73.         # CORE/INFO
  74.         s = read(4)
  75.         s = s + ImageFile._safe_read(self.fp, i32(s)-4)
  76.  
  77.         if len(s) == 12:
  78.  
  79.             # OS/2 1.0 CORE
  80.             bits = i16(s[10:])
  81.             self.size = i16(s[4:]), i16(s[6:])
  82.             compression = 0
  83.             lutsize = 3
  84.             colors = 0
  85.  
  86.         elif len(s) in [40, 64]:
  87.  
  88.             # WIN 3.1 or OS/2 2.0 INFO
  89.             bits = i16(s[14:])
  90.             self.size = i32(s[4:]), i32(s[8:])
  91.             compression = i32(s[16:])
  92.             lutsize = 4
  93.             colors = i32(s[32:])
  94.  
  95.         else:
  96.             raise IOError("Unsupported BMP header type (%d)" % len(s))
  97.  
  98.         if not colors:
  99.             colors = 1 << bits
  100.  
  101.         # MODE
  102.         try:
  103.             self.mode, rawmode = BIT2MODE[bits]
  104.         except KeyError:
  105.             raise IOError("Unsupported BMP pixel depth (%d)" % bits)
  106.  
  107.         if compression == 3:
  108.             # BI_BITFIELDS compression
  109.             mask = i32(read(4)), i32(read(4)), i32(read(4))
  110.             if bits == 32 and mask == (0xff0000, 0x00ff00, 0x0000ff):
  111.                 rawmode = "BGRX"
  112.             elif bits == 16 and mask == (0x00f800, 0x0007e0, 0x00001f):
  113.                 rawmode = "BGR;16"
  114.             elif bits == 16 and mask == (0x007c00, 0x0003e0, 0x00001f):
  115.                 rawmode = "BGR;15"
  116.             else:
  117.                 # print bits, map(hex, mask)
  118.                 raise IOError("Unsupported BMP bitfields layout")
  119.         elif compression != 0:
  120.             raise IOError("Unsupported BMP compression (%d)" % compression)
  121.  
  122.         # LUT
  123.         if self.mode == "P":
  124.             palette = []
  125.             greyscale = 1
  126.             if colors == 2:
  127.                 indices = (0, 255)
  128.             else:
  129.                 indices = range(colors)
  130.             for i in indices:
  131.                 rgb = read(lutsize)[:3]
  132.                 if rgb != chr(i)*3:
  133.                     greyscale = 0
  134.                 palette.append(rgb)
  135.             if greyscale:
  136.                 if colors == 2:
  137.                     self.mode = rawmode = "1"
  138.                 else:
  139.                     self.mode = rawmode = "L"
  140.             else:
  141.                 self.mode = "P"
  142.                 self.palette = ImagePalette.raw(
  143.                     "BGR", string.join(palette, "")
  144.                     )
  145.  
  146.         if not offset:
  147.             offset = self.fp.tell()
  148.  
  149.         self.tile = [("raw",
  150.                      (0, 0) + self.size,
  151.                      offset,
  152.                      (rawmode, ((self.size[0]*bits+31)>>3)&(~3), -1))]
  153.  
  154.         self.info["compression"] = compression
  155.  
  156.     def _open(self):
  157.  
  158.         # HEAD
  159.         s = self.fp.read(14)
  160.         if s[:2] != "BM":
  161.             raise SyntaxError("Not a BMP file")
  162.         offset = i32(s[10:])
  163.  
  164.         self._bitmap(offset=offset)
  165.  
  166.  
  167. class DibImageFile(BmpImageFile):
  168.  
  169.     format = "DIB"
  170.     format_description = "Windows Bitmap"
  171.  
  172.     def _open(self):
  173.         self._bitmap()
  174.  
  175. #
  176. # --------------------------------------------------------------------
  177. # Write BMP file
  178.  
  179. def o16(i):
  180.     return chr(i&255) + chr(i>>8&255)
  181.  
  182. def o32(i):
  183.     return chr(i&255) + chr(i>>8&255) + chr(i>>16&255) + chr(i>>24&255)
  184.  
  185. SAVE = {
  186.     "1": ("1", 1, 2),
  187.     "L": ("L", 8, 256),
  188.     "P": ("P", 8, 256),
  189.     "RGB": ("BGR", 24, 0),
  190. }
  191.  
  192. def _save(im, fp, filename, check=0):
  193.  
  194.     try:
  195.         rawmode, bits, colors = SAVE[im.mode]
  196.     except KeyError:
  197.         raise IOError("cannot write mode %s as BMP" % im.mode)
  198.  
  199.     if check:
  200.         return check
  201.  
  202.     stride = ((im.size[0]*bits+7)/8+3)&(~3)
  203.     header = 40 # or 64 for OS/2 version 2
  204.     offset = 14 + header + colors * 4
  205.     image  = stride * im.size[1]
  206.  
  207.     # bitmap header
  208.     fp.write("BM" +                     # file type (magic)
  209.              o32(offset+image) +        # file size
  210.              o32(0) +                   # reserved
  211.              o32(offset))               # image data offset
  212.  
  213.     # bitmap info header
  214.     fp.write(o32(header) +              # info header size
  215.              o32(im.size[0]) +          # width
  216.              o32(im.size[1]) +          # height
  217.              o16(1) +                   # planes
  218.              o16(bits) +                # depth
  219.              o32(0) +                   # compression (0=uncompressed)
  220.              o32(image) +               # size of bitmap
  221.              o32(1) + o32(1) +          # resolution
  222.              o32(colors) +              # colors used
  223.              o32(colors))               # colors important
  224.  
  225.     fp.write("\000" * (header - 40))    # padding (for OS/2 format)
  226.  
  227.     if im.mode == "1":
  228.         for i in (0, 255):
  229.             fp.write(chr(i) * 4)
  230.     elif im.mode == "L":
  231.         for i in range(256):
  232.             fp.write(chr(i) * 4)
  233.     elif im.mode == "P":
  234.         fp.write(im.im.getpalette("RGB", "BGRX"))
  235.  
  236.     ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, stride, -1))])
  237.  
  238. #
  239. # --------------------------------------------------------------------
  240. # Registry
  241.  
  242. Image.register_open(BmpImageFile.format, BmpImageFile, _accept)
  243. Image.register_save(BmpImageFile.format, _save)
  244.  
  245. Image.register_extension(BmpImageFile.format, ".bmp")
  246.